package com.ruoyi.jjyh.controller;

import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.*;
import com.ruoyi.jjyh.domain.*;
import com.ruoyi.jjyh.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

import static com.ruoyi.common.utils.Sha1Util.getNonceStr;


/**
 * 用户Controller
 * 
 * @author ruoyi
 * @date 2020-09-02
 */
@Controller
@RequestMapping(value = "/phone/jjyh/wxPay")
public class WxPayController extends BaseController {


    @Autowired
    private IJjyhOrderService jjyhOrderService;

    @Autowired
    private IJjyhPayrecordService jjyhPayrecordService;

    @Autowired
    private IJjyhMemberlevelService jjyhMemberlevelService;

    @Autowired
    private IJjyhUserService jjyhUserService;

    @Autowired
    private IJjyhUservalidaysService jjyhUservalidaysService;



    //微信支付商户开通后 微信会提供appid和appsecret和商户号partner
    @Value("${wxConfig.appId}")
    private String appId;

    @Value("${wxConfig.appSecret}")
    private String appSecret;

    @Value("${wxConfig.partner}")
    private String partner;

    @Value("${wxConfig.partnerKey}")
    private String partnerKey;

    @Value("${wxConfig.notifyUrl}")
    private String notifyUrl;

    @Value("${wxConfig.notifyUrlVIP}")
    private String notifyUrlVIP;



    /**
     * 微信支付
     * @param response
     * @return
     * @throws IOException
     */
    @ResponseBody
    @RequestMapping(value = "/wxPay")
    public AjaxResult wxPay(String orderId, String userId, HttpServletResponse response) throws IOException {
        response.setHeader("Access-Control-Allow-Origin", "*");
        //定义map类型的变量data，其中存放进行请求统一下单所需要的参数
        HashMap<String, String> data = new HashMap<String, String>();
        try {
            JjyhOrder order = jjyhOrderService.selectJjyhOrderById(orderId);
            String attach = "";
            String userInId = order.getUserInid();
            String userOutId = order.getUserOutid();
            if(userId.equals(userInId))attach = "in";
            if(userId.equals(userOutId))attach = "out";
            if(EmptyUtils.isEmpty(order)){
                return error("订单不存在");
            }
            Double money = order.getSecurityInmoney().doubleValue();



            String totalFee = String.valueOf(money);

            data.put("appid", appId);
            data.put("mch_id", partner);
            data.put("key", partnerKey);
            data.put("notify_url", notifyUrl);
            data.put("body", "保证金");
            data.put("attach", attach);
            data.put("spbill_create_ip", "127.0.0.1");
            data.put("out_trade_no", orderId  + StringUtils.getRandomString(6));

            data.put("total_fee",getMoney(totalFee));//付款金额

//            data.put("total_fee", "1");//付款金额
            WXPayRequest wxPayRequest = new WXPayRequest();
            Map<String, String> r = wxPayRequest.unifiedorder(data);
            System.out.println(r);
            String resultCode = r.get("result_code");
            if (resultCode.equals("SUCCESS")) {
                Map<String,Object> resultMap =new HashMap<String, Object>();
                resultMap.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
                resultMap.put("package", "Sign=WXPay");
                resultMap.put("appid", r.get("appid"));
                resultMap.put("partnerid", r.get("mch_id"));
                resultMap.put("prepayid", r.get("prepay_id"));
                resultMap.put("noncestr", r.get("nonce_str"));
                resultMap.put("sign", r.get("sign"));
                String newSing =  getSign(resultMap,partnerKey);
                resultMap.put("sign", newSing);
                return success("操作成功", resultMap);
            } else {
                logger.info(r.get("return_msg"));
                return error("订单支付异常");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return error("订单支付异常");
        }

    }





    /**
     * 元转换成分
     *
     * @param amount
     * @return
     */
    public static String getMoney(String amount) {
        if (amount == null) {
            return "";
        }
        // 金额转化为分为单位
        String currency = amount.replaceAll("\\$|\\￥|\\,", "");  //处理包含, ￥ 或者$的金额
        int index = currency.indexOf(".");
        int length = currency.length();
        Long amLong = 0l;
        if (index == -1) {
            amLong = Long.valueOf(currency + "00");
        } else if (length - index >= 3) {
            amLong = Long.valueOf((currency.substring(0, index + 3)).replace(".", ""));
        } else if (length - index == 2) {
            amLong = Long.valueOf((currency.substring(0, index + 2)).replace(".", "") + 0);
        } else {
            amLong = Long.valueOf((currency.substring(0, index + 1)).replace(".", "") + "00");
        }
        return amLong.toString();
    }


    /**
     * 微信回调
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/notify", method = RequestMethod.POST)
    @ResponseBody
    public String notify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        response.setHeader("Access-Control-Allow-Origin", "*");
        Map<String, String> result = new HashMap<String, String>();
        Map<String, String> params = null;
        String returnxml = "";
        InputStream inputStream;
        StringBuffer sb = new StringBuffer();
        //以字节流的形式读取request中的数据
        inputStream = request.getInputStream();
        String s;
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        while ((s = in.readLine()) != null) {
            sb.append(s);
        }
        in.close();
        inputStream.close();
        params = WXPayUtil.xmlToMap(sb.toString());
        logger.info("1.notify-params>>>>>>>>>>>:" + params);

        String returnCode = params.get("return_code");
        logger.info("3.returnCode:" + returnCode);
        if (returnCode.equals("SUCCESS")) {
            //判断签名是否正确
            boolean flag = isResponseSignatureValid(params);
            logger.info("2.notify-flag:" + flag);
            if (flag) {
                //获取微信订单号
                String transactionId = params.get("transaction_id");
                //获取商户订单号
                String outTradeNo = params.get("out_trade_no");
                //附加信息原路返回   recharge:充值 order:订单
                String attach = params.get("attach");//in 换入 被动  out换出 主动
                Integer total_fee = Integer.valueOf(params.get("total_fee"));//订单总金额，单位为分
                double total = total_fee * 0.01;
                logger.info("aaa====================================" + transactionId);
                logger.info("bbb====================================" + outTradeNo);
                logger.info("ccc====================================" + attach);
                //TODO  业务逻辑

                String orderId = outTradeNo.substring(0, outTradeNo.length()-6);
                JjyhOrder order = jjyhOrderService.selectJjyhOrderById(orderId);
                String userId = "";
                JjyhOrder order1 = new JjyhOrder();
                order1.setId(orderId);
                if("in".equals(attach)){
                    order1.setChangeInstatus("2");
                    userId = order.getUserInid();
                }
                if("out".equals(attach)){
                    order1.setChangeOutstatus("2");
                    userId = order.getUserOutid();
                }
                jjyhOrderService.updateJjyhOrder(order1);

                JjyhPayrecord payrecord = new JjyhPayrecord();
                payrecord.setId(IdWorker.getId());
                payrecord.setUserId(userId);
                payrecord.setOrderId(orderId);
                payrecord.setPayMoney(new BigDecimal(total).setScale(2, BigDecimal.ROUND_HALF_UP));
                payrecord.setPayMethod("微信");
                payrecord.setPayType("支付保证金");
                payrecord.setIsPay("1");
                payrecord.setPayid(transactionId);
                jjyhPayrecordService.insertJjyhPayrecord(payrecord);




                result.put("return_code", "SUCCESS");
                result.put("return_msg", "支付成功");
                logger.info("4.订单：" + outTradeNo + " 交易完成" + ">>>" + transactionId);
            } else {
                result.put("return_code", "FAIL");
                result.put("return_msg", "签名失败");
                logger.info("签名验证失败>>>>>>>>>>>>");
            }
        } else {
            result.put("return_code", "FAIL");
            result.put("return_msg", "支付失败");
            logger.info("");
        }
        returnxml = WXPayUtil.mapToXml(result);
        return returnxml;
    }


    public boolean isResponseSignatureValid(Map<String, String> param) throws Exception {
        return WXPayUtil.isSignatureValid(param, partnerKey, WXPayConstants.SignType.MD5);
    }



    @RequestMapping("/getWxShare")
    public @ResponseBody Map<String, String> init(String url)throws Exception{
//        url = URLEncoder.encode(url, "utf-8");
        String jsapi_ticket = WeiXinUtil.getJsapiTicket(WeiXinUtil.getAccessToken(appId, appSecret).getAccessToken());



        Map<String, String> ret = sign(jsapi_ticket, url);

        System.out.println("currurl = "+ url);

        // 注意 URL 一定要动态获取，不能 hardcode
//		for (Map.Entry entry : ret.entrySet()) {
//			System.out.println(entry.getKey() + ", " + entry.getValue());
//		}
        System.out.println("signature =" + ret.get("signature"));
        return ret;
    }

    public String getSign(Map<String, Object> data,String key) throws Exception {
        Set<String> keySet = data.keySet();
        String[] keyArray = keySet.toArray(new String[keySet.size()]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder();
        for (String k : keyArray) {
            if (k.equals(WXPayConstants.FIELD_SIGN)) {
                continue;
            }
            if (data.get(k).toString().trim().length() > 0) // 参数值为空，则不参与签名
                sb.append(k).append("=").append(data.get(k).toString().trim()).append("&");
        }
        sb.append("key=").append(key);
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        byte[] array = new byte[0];
        try {
            array = md.digest(sb.toString().getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        StringBuilder sb2 = new StringBuilder();
        for (byte item : array) {
            sb2.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
        }
        return sb2.toString().toUpperCase();
    }


    public Map<String, String> sign(String jsapi_ticket, String url) {
        Map<String, String> ret = new HashMap<String, String>();
        String nonce_str = create_nonce_str();
        String timestamp = create_timestamp();
        String string1;
        String signature = "";

        // 注意这里参数名必须全部小写，且必须有序
        string1 = "jsapi_ticket=" + jsapi_ticket +
                "&noncestr=" + nonce_str +
                "&timestamp=" + timestamp +
                "&url=" + url;
        System.out.println(string1);

        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        ret.put("url", url);
        ret.put("appId",appId);
//        ret.put("jsapi_ticket", jsapi_ticket);
        ret.put("nonceStr", nonce_str);
        ret.put("timestamp", timestamp);
        ret.put("signature", signature);

        return ret;
    }

    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash) {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

    private static String create_nonce_str() {
        return UUID.randomUUID().toString();
    }

    private static String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }


    /**
     * 微信支付 -- 购买会员
     * @param response
     * @return
     * @throws IOException
     */
    @ResponseBody
    @RequestMapping(value = "/wxPayVip")
    public AjaxResult wxPayVip(String userId,String id, HttpServletResponse response) throws IOException {
        response.setHeader("Access-Control-Allow-Origin", "*");
        //定义map类型的变量data，其中存放进行请求统一下单所需要的参数
        HashMap<String, String> data = new HashMap<String, String>();
        try {
            JjyhMemberlevel memberlevel = jjyhMemberlevelService.selectJjyhMemberlevelById(id);

            BigDecimal needMoney = memberlevel.getNeedMoney();

            JjyhPayrecord payrecord = new JjyhPayrecord();
            payrecord.setId(IdWorker.getId());
            payrecord.setUserId(userId);
            payrecord.setPackageId(id);
            payrecord.setPayMoney(needMoney);
            payrecord.setPayMethod("微信");
            payrecord.setPayType("购买会员");
            payrecord.setIsPay("0");
            jjyhPayrecordService.insertJjyhPayrecord(payrecord);


            Double money = needMoney.doubleValue();



            String totalFee = String.valueOf(money);

            data.put("appid", appId);
            data.put("mch_id", partner);
            data.put("key", partnerKey);
            data.put("notify_url", notifyUrlVIP);
            data.put("body", "购买VIP");
            data.put("spbill_create_ip", "127.0.0.1");
            data.put("out_trade_no", payrecord.getId()  + StringUtils.getRandomString(6));

//            data.put("total_fee",getMoney(totalFee));//付款金额
            data.put("total_fee", "1");//付款金额
            WXPayRequest wxPayRequest = new WXPayRequest();
            Map<String, String> r = wxPayRequest.unifiedorder(data);
            System.out.println(r);
            String resultCode = r.get("result_code");
            if (resultCode.equals("SUCCESS")) {
                Map<String,Object> resultMap =new HashMap<String, Object>();
                resultMap.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
                resultMap.put("package", "Sign=WXPay");
                resultMap.put("appid", r.get("appid"));
                resultMap.put("partnerid", r.get("mch_id"));
                resultMap.put("prepayid", r.get("prepay_id"));
                resultMap.put("noncestr", r.get("nonce_str"));
                resultMap.put("sign", r.get("sign"));
                String newSing =  getSign(resultMap,partnerKey);
                resultMap.put("sign", newSing);
                return success("操作成功", resultMap);
            } else {
                logger.info(r.get("return_msg"));
                return error("订单支付异常");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return error("订单支付异常");
        }

    }


    /**
     * 微信回调
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/notifyVIP", method = RequestMethod.POST)
    @ResponseBody
    public String notifyVIP(HttpServletRequest request, HttpServletResponse response) throws Exception {
        response.setHeader("Access-Control-Allow-Origin", "*");
        Map<String, String> result = new HashMap<String, String>();
        Map<String, String> params = null;
        String returnxml = "";
        InputStream inputStream;
        StringBuffer sb = new StringBuffer();
        //以字节流的形式读取request中的数据
        inputStream = request.getInputStream();
        String s;
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        while ((s = in.readLine()) != null) {
            sb.append(s);
        }
        in.close();
        inputStream.close();
        params = WXPayUtil.xmlToMap(sb.toString());
        logger.info("1.notify-params>>>>>>>>>>>:" + params);

        String returnCode = params.get("return_code");
        logger.info("3.returnCode:" + returnCode);
        if (returnCode.equals("SUCCESS")) {
            //判断签名是否正确
            boolean flag = isResponseSignatureValid(params);
            logger.info("2.notify-flag:" + flag);
            if (flag) {
                //获取微信订单号
                String transactionId = params.get("transaction_id");
                //获取商户订单号
                String outTradeNo = params.get("out_trade_no");
                //附加信息原路返回   recharge:充值 order:订单
                Integer total_fee = Integer.valueOf(params.get("total_fee"));//订单总金额，单位为分
                double total = total_fee * 0.01;
                logger.info("aaa====================================" + transactionId);
                logger.info("bbb====================================" + outTradeNo);
                //TODO  业务逻辑

                String id = outTradeNo.substring(0, outTradeNo.length()-6);

                JjyhPayrecord payrecord = jjyhPayrecordService.selectJjyhPayrecordById(id);
                JjyhMemberlevel memberlevel = jjyhMemberlevelService.selectJjyhMemberlevelById(payrecord.getPackageId());


                JjyhPayrecord payrecord1 = new JjyhPayrecord();
                payrecord1.setId(id);
                payrecord1.setIsPay("1");
                payrecord1.setPayid(transactionId);
                jjyhPayrecordService.updateJjyhPayrecord(payrecord1);

                JjyhUser user = jjyhUserService.selectJjyhUserById(payrecord.getUserId());
                JjyhUser user1 = new JjyhUser();
                user1.setId(user.getId());

                Date endTime = user.getEndTime();
                if(EmptyUtils.isEmpty(endTime)){
                    user1.setEndTime(DateUtils.handleDate(memberlevel.getActivityMonth()));
                }else{
                    Long endTimeLong = user.getEndTime().getTime();
                    Long nowTime = System.currentTimeMillis();
                    if(nowTime > endTimeLong){
                        user1.setEndTime(DateUtils.handleDate(memberlevel.getActivityMonth()));
                    }else{
                        user1.setEndTime(DateUtils.handleDate(endTime,memberlevel.getActivityMonth()));
                    }
                }
                user1.setViewTimes(user.getViewTimes() + memberlevel.getPhoneTimes());
                user1.setLevel(memberlevel.getId());
                jjyhUserService.updateJjyhUser(user1);

                JjyhUservalidays uservalidays = new JjyhUservalidays();
                uservalidays.setId(IdWorker.getId());
                uservalidays.setUserId(user.getId());
                uservalidays.setSendDays(memberlevel.getActivityMonth());
                if("834598284730306560".equals(memberlevel.getId())){
                    uservalidays.setSendType("3");
                }
                if("834598356696174592".equals(memberlevel.getId())){
                    uservalidays.setSendType("4");
                }

                jjyhUservalidaysService.insertJjyhUservalidays(uservalidays);


                result.put("return_code", "SUCCESS");
                result.put("return_msg", "支付成功");
                logger.info("4.订单：" + outTradeNo + " 交易完成" + ">>>" + transactionId);
            } else {
                result.put("return_code", "FAIL");
                result.put("return_msg", "签名失败");
                logger.info("签名验证失败>>>>>>>>>>>>");
            }
        } else {
            result.put("return_code", "FAIL");
            result.put("return_msg", "支付失败");
            logger.info("");
        }
        returnxml = WXPayUtil.mapToXml(result);
        return returnxml;
    }

}
